#include "uefi.h"

// Author: you-call-this-a-project (foolish-shabby <2276316223@qq.com>)
// Just some POSIX wraps.
// 就一些 POSIX 包装

typedef void (*atexit_func)(void);
static atexit_func __atexit_stack[100]; // 100 >= 32
static int __atexit_stack_top = -1;
static int __atexit_stack_len = 0;

void *malloc(size_t size)
{
    void *res = NULL;
    EFI_STATUS status = gBS->AllocatePool(
        LIP ? LIP->ImageDataType : EfiLoaderData,
        size,
        &res
    );
    if (EFI_ERROR(status) || !res) return NULL;
    return res;
}

void free(void *buffer)
{
    gBS->FreePool(buffer);
}

void *calloc(size_t nmemb, size_t size)
{
    void *res = malloc(nmemb * size);
    if (res) memset(res, 0, nmemb * size);
    return res;
}

void *realloc(void *buffer, int size)
{
    void *res = NULL;
    if (!buffer) return malloc(size);
    if (!size) {
        free(buffer);
        return NULL;
    }
    res = malloc(size);
    memcpy(res, buffer, size);
    free(buffer);
    return res;
}

int atexit(atexit_func func)
{
    if (__atexit_stack_len == 100) {
        return -1;
    }
    __atexit_stack[++__atexit_stack_top] = func;
    __atexit_stack_len++;
    return 0;
}

void _exit(int status)
{
    gBS->Exit(gIM, !status ? 0 : (status < 0 ? EFIERR(-status) : EFIERR(status)), 0, NULL);
}

void exit(int status)
{
    while (__atexit_stack_len) {
        atexit_func func = __atexit_stack[__atexit_stack_top--];
        func();
        __atexit_stack_len--;
    }
    _exit(status);
}